package com.gzz.retail.domain;
/**
 * 领域层
 * domain 领域层
 * 领域层主要负责表达业务概念，业务状态信息和业务规则。
 * Domain层是整个系统的核心层，几乎全部的业务逻辑会在该层实现。
 * <p>
 * 主要包含以下的内容：
 * <p>
 * 领域服务（Domain Services）：
 *      一些行为无法归类到实体对象或值对象，本质是一些操作，而非事物。
 *      领域服务。区别于应用服务，他属于业务领域层。
 *      可以认为，如果某种行为无法归类给任何实体/值对象，则就为这些行为建立相应的领域服务即可。
 *      比如：转账服务（transferService），需要操作借方/贷方两个账户实体。
 *      传统意义上的util static方法中，涉及到业务逻辑的部分，都可以考虑归入domain services
 *
 * 聚合/ 聚合根（Aggregates,Aggregate Roots）：
 *          聚合是指一组具有内聚关系的相关对象的集合，每个聚合都有一个ROOT和Boundary
 * <p>
 *     Domain Primitive
 * <p>
 * 类型 	      英文 	         描述
 * 值对象 	      value object 	 无唯一标识的简单对象
 * 实体 	      entity 	     充血的领域模型，有唯一标识的对象
 * 聚合（聚合根）  aggregate 	 实体的聚合，拥有聚合根，可为某一个实体
 *
 * 领域服务 	      service 	      有些领域中的动作，它们是一些动词，看上去却不属于任何对象。它们代表了领域中的一个重要的行为，
 *                                所以不能忽略它们或者简单地把它们合并到某个实体或者值对象中。
 *                                <b>当这样的行为从领域中被识别出来时，最佳实践是将它声明成一个服务</b>
 *
 *                              识别领域服务，主要看它是否满足以下三个特征：
 *                               1. 服务执行的操作代表了一个领域概念，这个领域概念无法自然地隶属于一个实体或者值对象。
 *                               2. 被执行的操作涉及到领域中的其他的对象。
 *                               3. 操作是无状态的。
 *
 *                                无法归类到某个具体领域模型的行为（如：用户登录验证）
 *                                 1, 执行一个显著的业务操作过程
 *                                 2, 对领域对象进行转换
 *                                 3, 以多个领域对象作为输入进行计算，结果产生一个值对象（这点需要该操作具有显著的业务操作过程特点）
 *
 *                                领域中的服务表示一个无状态的操作，它用于实现特定于某个领域的任务。
 *                                这里我们要搞清楚什么样的操作需要实体，值对象，什么样的操作需要采用领域服务。
 *                                另外，领域服务不是应用服务，在应用服务中我们不需要处理业务逻辑，业务逻辑都落在领域服务中。
 *
 * 领域事件 	      event 	     不常用  领域事件通常是用来与其他聚合解耦的，采用观察者模式，一个聚合订阅另外一个聚合的事件。
 * 仓储 	      repository 	 持久化相关，与基础设施层关联
 *                                仓储由应用服务层调用
 *
 * 工厂 	      factory 	     负责创建复杂对象。
 *                               工厂有两大场景，一个是用来新建对象，一个是用来重塑对象。
 *
 * 模块 	      module 	     子模块引入，可以理解为子域划分
 * <p>
 * <p>
 * #########################################################################################################
 * domain层包含entity（实体）、valueobject(值对象)、domain event（领域事件）和repository（仓储）
 *
 * 领域层根据包名和好理解。
 * converter：转行器，把DO（data object 数据对象，即数据库对于的表）和DTO进行转换、实体和DO进行转换。
 * entity：实体，如聚合根、实体等。
 * event: 领域事件， 领域事件产生的时机为当聚合根的状态改变时，如订单已支付、订单已取消等状态改变时会产生领域事件。
 * factory：工厂方法， 很多用例都推崇使用工厂方法来创建聚合根， 但是也有缺陷，当聚合根的成员很多时， 构造方法参数很多， 这时候，建议通过建造者模式来创建聚合根。参看下面代码。
 * repository：仓储，即对聚合根进行存储的接口， 同时我把实现类也放在这里的原因是，如果实现类放在基础设施层，那么需要在基础设施层依赖领域层进行对象的装换。
 * representation：跟应用层一样
 * service：领域服务，聚合根是业务逻辑的主要载体，也就是说业务逻辑的实现代码应该尽量地放在聚合根或者聚合根的边界之内。但有时，有些业务逻辑并不适合于放在聚合根上，如我们保存订单（order）的时候需要同时保存订单品相（order_item）,涉及到两个实体的操作，在这种迫不得已的情况下，那么引入领域服务（Domain Service），尽量少用吧。
 * valuepbject： 值对象，如订单（order）里面的收货地址（address），尽量少用值对象，除非你非常明确它就是值对象，否则建议都用实体，如果不合理，在代码的演进过程中进行修改和完善。例如订单（Order）实体包括订单品相（Order_item）和收货地址（Address）, 我设置Order_item为实体、Address为值对象的原因是Order_item是需要单独持久化到数据库中。
 * ————————————————
 * 版权声明：本文为CSDN博主「我很爱吃榴莲」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
 * 原文链接：https://blog.csdn.net/w1054993544/article/details/105287944
 */